import { Button, Message, Modal, Upload } from '@arco-design/web-react';
import { RequestOptions, UploadInstance, UploadItem } from '@arco-design/web-react/es/Upload';
import { ReactNode, useRef, useState } from 'react';
import { isArray } from '../utils/utils';
import { apiUploadFile } from '../api';
import { randomString } from '../utils/utils';
import main from '../main';
import dayjs from 'dayjs';
const imageFileType = ['jpg', 'png', 'gif', 'bmp', 'svg', 'jpeg', 'webp'];
export interface SuccessUploadItem extends UploadItem {
  response: {
    code: number;
    msg?: string;
    data?: {
      fileName?: string;
      ossId?: string;
      url?: string;
    };
  };
}

interface Props {
  /** 显示弹窗 */
  show?: boolean;
  /** 允许的文件类型 image/*=>任意图片 * /* =>任意文件  .xxx|xxx =>指定一种类型 .xxx,.ss,.yy=>指定多种类型 可以不带.  */
  accept?: 'image/*' | '*/*' | string;
  /** 自动上传 选了文件就上传 否则需要点击上传按钮才开始上传 */
  autoUpload?: boolean;
  /** 返回的数据只有url 优先级1 否则返回UploadItem[] 可取item.response.data.url */
  onlyReturnUrl?: boolean;
  /** 返回的数据只有id 优先级2 否则返回UploadItem[] 可取item.response.data.ossId */
  onlyReturnId?: boolean;
  /** 返回的数据只有File对象 优先级3 否则返回UploadItem[] 可取item.originFile */
  onlyReturnFile?: boolean;
  /** 上传数量  */
  limit?: number;
  /** 是否可多选 */
  multi?: boolean;
  /** 上传组件上方要显示的组件 */
  headerChild?: ReactNode;
  /** 上传组件下方要显示的组件 */
  otherChild?: ReactNode;
  /** 弹窗标题 */
  title?: string;
  /** 是否上传到aliyun */
  toAliyun?: boolean;
  /** 上传到aliyun的目录 */
  toAliyunPath?: string;
  /** 上传到aliyun的文件名 以防重复 */
  toAliyunName?: string;
  /** 显示内容 有此值会替换上传组件 */
  children?: ReactNode;
  /** 弹窗样式类 */
  className?: string;
  /** 弹窗内容样式类 */
  contentClassName?: string;
  /** 上传文件大小 */
  fileSize?: number;
  /** 取消按钮方法 */
  onCancel?: () => void;
  /** 确定按钮方法 */
  onConfirm?: (list: any) => void;
}
export default function OssUploadDialog({
  show = false,
  autoUpload = true,
  onlyReturnUrl = false,
  onlyReturnId = false,
  onlyReturnFile = false,
  limit = 1,
  multi = true,
  accept = '*/*',
  onConfirm,
  onCancel,
  otherChild,
  headerChild,
  title,
  toAliyun = false,
  toAliyunPath,
  toAliyunName,
  className,
  contentClassName,
  children,
  fileSize,
}: Props) {
  const pageTitle = title ?? '文件上传';
  const uploadRef = useRef<UploadInstance | null>(null);
  const [confirm, setCofirm] = useState(false);
  const fileListRef = useRef<UploadItem[]>();
  const [fileList, setFileList] = useState<UploadItem[]>([]);

  function handleCancel() {
    closeAndClear();
    onCancel && onCancel();
  }
  // 验证文件格式
  function isAcceptFile(file?: File, accept?: string) {
    if (accept === '*/*') return true;
    if (fileSize && file!.size / 1024 / 1024 > fileSize) {
      Message.error('上传2M以内的图片');
      return false;
    }
    if (accept && file) {
      const fileExtension: string = (file.name.indexOf('.') > -1 ? file.name.split('.').pop() : '') ?? '';
      if (accept === 'image/*' && imageFileType.includes(fileExtension)) return true;
      const accepts = Array.isArray(accept) ? accept : accept.split(',').map((x) => x.trim());
      return accepts.some((type) => {
        const text = type && type.toLowerCase();
        const fileType = fileExtension.toLowerCase();
        return text === fileType || `.${text}`.replaceAll('..', '.') === `.${fileType}`.replaceAll('..', '.');
      });
    }
    return !!file;
  }

  function checkImgType() {
    if (accept === 'image/*') return true;
    let list = Array.isArray(accept) ? accept : accept.split(',');
    for (let i of list) {
      if (imageFileType.includes(i.replaceAll('.', ''))) {
        return true;
      }
    }
    return false;
  }

  // 关闭弹窗时清空数据
  function closeAndClear() {
    setCofirm(false);
    fileListRef.current = undefined;
    setFileList([]);
  }

  function handleStartUpload() {
    let _fileList = fileListRef.current ?? [];
    if (!_fileList.length) {
      return Message.warning('请选择文件');
    }
    if (!autoUpload && uploadRef.current) {
      uploadRef.current.submit();
    }
  }

  function success() {
    let _fileList = fileListRef.current ?? [];
    let list: string[] | SuccessUploadItem[] = [];
    if (onlyReturnUrl) {
      // @ts-ignore
      list = _fileList.filter((i) => i.status === 'done').map((i) => i.response!.data.url);
    } else if (onlyReturnId) {
      // @ts-ignore
      list = _fileList.filter((i) => i.status === 'done').map((i) => i.response!.data.ossId);
    } else if (onlyReturnFile) {
      // @ts-ignore
      list = _fileList.map((i) => i.originFile);
    } else {
      list = _fileList.filter((i) => i.status === 'done') as SuccessUploadItem[];
    }

    closeAndClear();
    onConfirm && onConfirm(list);
    onCancel && onCancel();
  }

  // 确定按钮
  async function handleConfirm() {
    if (children) {
      success();
      return;
    }
    let _fileList = fileListRef.current ?? [];
    if (onlyReturnFile) {
      success();
      return;
    }
    if (confirm) return;
    if (!autoUpload) {
      let unupload = _fileList.some((i) => i.status === 'init' || i.status === 'uploading');
      if (unupload) {
        handleStartUpload();
        setCofirm(true);
        return;
      }
    }
    success();
  }

  function createFilePath(fileName: string) {
    if (toAliyun && toAliyunPath) {
      let preFileName = toAliyunName ? toAliyunName + '_' : '';
      return `${toAliyunPath}/${preFileName}${fileName}`.replaceAll('//', '/');
    }
    let exa = fileName.split('.').pop();
    let time = dayjs();
    let path = `${main.ossBasePath}${time.year()}/${time.month() + 1}/${time.date()}/${time.format(
      'YYYYMMDD'
    )}${randomString(16)}.${exa}`;
    return path;
  }

  // 上传
  async function handleUpload(options: RequestOptions) {
    if (!isAcceptFile(options.file, accept)) {
      return;
    }
    // try {
    //   let res = await apiUploadFile(options.file, (l, t) => {
    //     let procress = (l / t) * 100;
    //     procress = procress > 100 ? 100 : procress;
    //     options.onProgress(procress);
    //   });
    //   let data = res.data;
    //   if (data.code === 200) {
    //     options.onSuccess(data);
    //   } else {
    //     options.onError(data);
    //   }
    // } catch (e) {
    //   options.onError();
    // }
    // if (toAliyun) {
    //   try {
    //     let name = createFilePath(options.file.name);
    //     let res = await main.aliOssClient.multipartUpload(name, options.file, {
    //       progress: (p) => {
    //         let procress = p * 100;
    //         procress = procress > 100 ? 100 : procress;
    //         options.onProgress(procress);
    //       },
    //     });
    //     options.onSuccess({
    //       code: 200,
    //       data: {
    //         fileName: options.file.name,
    //         ossId: name.split('/').pop()?.split('.').shift(),
    //         // @ts-ignore
    //         url: res.res!.requestUrls[0].split('?').shift(),
    //       },
    //       msg: 'ok',
    //     });
    //   } catch (e: any) {
    //     options.onError(e.message ?? '上传失败');
    //   }
    // } else {
      try {
        let res = await apiUploadFile(options.file, (l, t) => {
          let procress = (l / t) * 100;
          procress = procress > 100 ? 100 : procress;
          options.onProgress(procress);
        });
        let data = res.data;
        if (data.code === 200) {
          options.onSuccess(data);
        } else {
          options.onError(data);
        }
      } catch (e) {
        options.onError();
      }
    // }
  }

  // 文件变化
  async function handleChange(fl: UploadItem[], file: UploadItem) {
    let _list: UploadItem[] = [];
    for (let item of fl) {
      if (!isAcceptFile(item.originFile, accept)) {
        Message.warning('错误的文件类型：' + (item.name ?? ''));
      } else {
        if (item.status === 'done' && !item.url) {
          // @ts-ignore
          item.url = item.response!.data.url;
        }
        _list.push(item);
      }
    }
    fileListRef.current = _list;
    setFileList(_list);
    if (confirm) {
      let unupload = _list.some((i) => i.status === 'init' || i.status === 'uploading');
      if (!unupload) {
        success();
      }
    }
  }

  if (!show) return null;
  let loading = fileList.some((i) => i.status === 'uploading') && !autoUpload;
  let _children: Array<any> = isArray(children) ? (children as Array<any>) : [children];
  let _tmp: Array<any> = [];
  if (isArray(children)) {
    _children.forEach((i) => {
      if (!!i) {
        _tmp.push(i);
      }
    });
  }
  return (
    <Modal
      className={className}
      title={pageTitle}
      visible={show}
      onCancel={handleCancel}
      footer={
        <>
          <Button onClick={handleCancel}>取消</Button>
          <Button type="primary" disabled={loading} onClick={handleConfirm}>
            {!autoUpload && !onlyReturnFile ? '上传' : '确定'}
          </Button>
        </>
      }
    >
      <div className={contentClassName}>
        {headerChild}
        {_tmp.length ? (
          _tmp
        ) : (
          <Upload
            drag
            accept={accept}
            ref={uploadRef}
            listType={checkImgType() ? 'picture-list' : 'text'}
            multiple={multi && limit > 1}
            autoUpload={autoUpload}
            limit={limit}
            fileList={fileList}
            onChange={handleChange}
            customRequest={handleUpload}
            onExceedLimit={() => Message.warning(`最多可选${limit}个文件`)}
          />
        )}
        {otherChild}
      </div>
    </Modal>
  );
}
